/**
 * Created by Administrator on 2015/6/11.
 */
class GameMain extends egret.DisplayObjectContainer{
    private StageW:number;
    private StageH:number;
    private _unitCache:GameUnit[];
    private row:number = 7;
    private col:number = 7;
    private startX:number = 40;
    private startY:number = 300;
    private unitContainer:egret.DisplayObjectContainer;

    private inProcessing:boolean;
    private unitMap:Object = {};
    //private scoreCon:egret.DisplayObjectContainer;
    private effectCon:egret.DisplayObjectContainer;
    private initValues:number[];
    private tree:DukeTree;

    private scoreTf:egret.TextField;
    private maxNumTf:egret.TextField;
    private bloodTf:egret.TextField;
    public constructor(){
        super();
        this.addEventListener(egret.Event.ADDED_TO_STAGE, this.onAddedToStage, this);
    }

    private onAddedToStage(event:egret.Event){
        this.removeEventListener(egret.Event.ADDED_TO_STAGE, this.onAddedToStage, this);
        EventController.getInstance().addEventListener(EventController.FAIL, this.onFail,this);
        if( this._unitCache == null){
            this._unitCache = [];
            this.StageH = this.stage.stageHeight;
            this.StageW = this.stage.stageWidth;

            this.scoreTf = new egret.TextField();
            this.scoreTf.text = "得分：0";
            this.scoreTf.fontFamily = "微软雅黑";
            this.scoreTf.x = 10;
            this.scoreTf.y = 20;
            this.scoreTf.touchEnabled = false;
            this.addChild(this.scoreTf);

            this.maxNumTf = new egret.TextField();
            this.maxNumTf.text = "最大：0";
            this.maxNumTf.fontFamily = "微软雅黑";
            this.maxNumTf.x = 10;
            this.maxNumTf.y = 70;
            this.maxNumTf.touchEnabled = false;
            this.addChild(this.maxNumTf);

            this.bloodTf = new egret.TextField();
            this.bloodTf.text = "机会：5";
            this.bloodTf.fontFamily = "微软雅黑";
            this.bloodTf.x = 10;
            this.bloodTf.y = 120;
            this.bloodTf.touchEnabled = false;
            this.addChild(this.bloodTf);
            this.initGame();
        }
    }

    private statisticMap:Object;
    private onFail(evt:egret.Event){
        this.statisticMap = {};
        var value:number;
        var key;
        var unit:GameUnit;
        for( key in this.unitMap){
            unit = this.unitMap[key];
            value = unit.getValue();
            if( this.statisticMap[value]  == null){
                this.statisticMap[value] = [];
            }
            this.statisticMap[value].push(key);
        }
        this.doScoreStatistic();

    }

    private doScoreStatistic(){
        var con:SomeContainer;
        var len:number;
        var temparr:string[];
        var temparr1:string[];
        var tw:egret.Tween;
        var value:number;
        var unitWidth:number = GameUnit.UNIT_WIDTH;
        var flag:boolean;
        var unit:GameUnit;
        this.isOver = true;
        //this.score = Model.score;
        var key;
        for(key in this.statisticMap){
            temparr = this.statisticMap[key];
            len = temparr.length;
            for(var i:number=0 ; i< len; i++){
                value = parseInt(key)*10;
                unit = this.unitMap[temparr[i]];
                temparr1 = temparr[i].split("_");
                con = new SomeContainer();
                //game.GetNum(value,con,1,false);
                this.score += value;
                this.scoreTf.text = "得分："+this.score;

                con.x = (parseInt(temparr1[0])-0.3)*unitWidth;
                con.y = parseInt(temparr1[1])*unitWidth;
                con.alpha = 0;
                tw = egret.Tween.get(con,null,null,true);
                this.effectCon.addChild(con);
                tw.to({y:con.y-80,alpha:1},500).call( con.removeSelf,con);
                ShakeMgr.instance().addShakeItem(unit.name,{gap:5,cnt:5,dis:unit,ox:(parseInt(temparr1[0]))*unitWidth,type:"shakeh"});
            }
            flag = true;
            delete this.statisticMap[key];
            break;
        }
        //GameMainPanel.getInstance().startScrollScore();
        if( flag ){
            egret.setTimeout(this.doScoreStatistic,this,600);
        }else{
            egret.setTimeout(this.showGameOver,this,600);
        }
    }
    public score:number = 0;
    private isOver:boolean;
    private showGameOver(){
        this.effectCon.removeChildren();
        GameConst.GrayMask.visible = true;
    }

    private initGame(){
        this.tree = new DukeTree();
        //this.psystem = new particle.GravityParticleSystem(RES.getRes(this.currentTextureName),RES.getRes("particle_json"));

        this.unitContainer = new egret.DisplayObjectContainer();
        this.unitContainer.x = this.startX;
        this.unitContainer.y = this.startY;
        this.addChild(this.unitContainer);
        this.effectCon = new egret.DisplayObjectContainer();
        this.addChild(this.effectCon);
        this.effectCon.x = this.startX;
        this.effectCon.y = this.startY;
        this.effectCon.touchChildren = this.effectCon.touchEnabled = false;
        this.stage.addEventListener(egret.TouchEvent.TOUCH_TAP,this.onTouchUnit, this);
        var unit:GameUnit;
        var gap:number = GameUnit.UNIT_WIDTH;
        this.getInitValues();
        for(var i:number = 0; i < this.col; i++){
            for(var j:number=0; j < this.row; j++){
                unit = this.produceUnit();
                unit.setValue(this.initValues[i*this.col+j]);
                unit.x = i * gap;
                unit.y = j * gap;
                this.unitContainer.addChild(unit);
                unit.name = i+"_"+j;
                this.unitMap[i+"_"+j] = unit;
            }
        }
    }

    private getInitValues(){
        this.initValues = [];
        var value:number;
        var elematedValues:number[];
        for(var i:number = 0; i < this.col; i++){
            for(var j:number=0; j < this.row; j++){
                elematedValues = [];
                value = this.getRandomValue();
                this.result = 0;
                this.checkValue(value,i, j);
                while(this.result >= 2){
                    elematedValues.push(value);
                    value = this.getRandomValue();
                    while(elematedValues.indexOf(value) != -1){
                        value = this.getRandomValue();
                    }
                    this.result = 0;
                    this.checkValue(value,i, j);
                }
                this.initValues.push(value);
            }
        }
        this.maxNumTf.text = "最大："+this.curMax;
    }
    private result:number = 0;
    private checkValue(value:number, col:number, row:number,needLoop:boolean=true,rawCol:number=0,rawRow:number=0){
        var hasNum:Number;
        var index:number = col * this.col + (row-1);
        if( index >=0 && index < this.initValues.length && this.initValues[index] == value && (col != rawCol || row != rawRow)){
            this.result++;
            if( needLoop ){
                this.checkValue(value, col, row-1,false,col,row);
            }
        }
        if( this.result >= 2) return;
        index = col * this.col + (row + 1);
        if( index >=0 && index < this.initValues.length && this.initValues[index] == value && (col != rawCol || row != rawRow)){
            this.result++;
            if( needLoop ){
                this.checkValue(value, col, row+1,false,col,row);
            }
        }
        if( this.result >= 2) return;
        index = (col-1) * this.col + row;
        if( index >=0 && index < this.initValues.length && this.initValues[index] == value && (col != rawCol || row != rawRow)){
            this.result++;
            if( needLoop ){
                this.checkValue(value, col-1, row, false,col,row);
            }
        }

        if( this.result >= 2) return;
        index = (col+1) * this.col + row;
        if( index >=0 && index < this.initValues.length && this.initValues[index] == value && (col != rawCol || row != rawRow)){
            this.result++;
            if( needLoop ){
                this.checkValue(value, col + 1, row,false,col,row);
            }
        }
    }

    private curMax:number=0;
    private curSeed:number = 8;
    private getRandomValue():number
    {
        var seed:number = this.curSeed < 8 ?  8 : this.curSeed;
        var value:number = Math.ceil(Math.random()*seed);
        this.curMax = this.curMax > value ? this.curMax : value;
        return value;
    }
    private setCurMax(value:number){
        if( value <= this.curMax ) return;
        this.curMax = value > this.curMax ? value : this.curMax;
        this.curSeed = this.curMax/2+1;
        this.maxNumTf.text = "最大："+this.curMax;
    }
    private deleteArr:GameUnit[] = [];
    private selectedUnit:GameUnit;
    private bonus:number;
    private blood:number = 5;
    private onTouchUnit(event:egret.TouchEvent){
        if( this.inProcessing || this.isOver)
          return;

        if(event.target instanceof GameUnit){
            this.bonus = 0;
            this.inProcessing = true;
            this.selectedUnit = event.target;
            var node:DukeNode;
            var value:number = this.selectedUnit.getValue();
            //if( value < 20 )
            //{
            //    SoundMgr.getInstance().playEffect(SoundMgr.EFFECT_BTN);
                value++;
                this.setCurMax(value);
                this.curMax = this.curMax > value ? this.curMax : value;
                node = DukeTree.produce();
                node.data = this.selectedUnit;
                this.tree.reset();
                this.tree.setRoot(node);
                this.selectedUnit.setValue(value);
                this.deleteArr = [];
                this.checkDelete(node);
                var len:number = this.deleteArr.length;
                if( len >= 2)
                {
                    this.score += len+1;
                    this.scoreTf.text = "得分："+this.score;
                    this.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
                    SoundMgr.getInstance().playEffect("1hit_wav");
                }else{
                    this.inProcessing = false;
                    this.blood--;
                    if( this.blood <= 0)
                        this.doScoreStatistic();
                }
            //}else{
            //    this.doScoreStatistic();
            //}
        }
    }

    private checkDelete(node:DukeNode){
        var unit:GameUnit = node.data;
        if( unit == null) return;
        var tnode:DukeNode;
        var arr:any[] = unit.name.split("_");
        var col:number = parseInt(arr[0]);
        var row:number = parseInt(arr[1]);
        var value:number = unit.getValue();
        var unit:GameUnit = this.unitMap[(col+1)+"_"+row];
        if( unit != null && unit.getValue() == value && this.deleteArr.indexOf(unit) == -1 && unit != this.selectedUnit)
        {
            tnode = DukeTree.produce();
            tnode.data = unit;
            this.deleteArr.push(unit);
            node.addChild(tnode);
            this.checkDelete(tnode);
        }

        unit = this.unitMap[(col-1)+"_"+row];
        if( unit != null && unit.getValue() == value && this.deleteArr.indexOf(unit) == -1 && unit != this.selectedUnit)
        {
            tnode = DukeTree.produce();
            tnode.data = unit;
            this.deleteArr.push(unit);
            node.addChild(tnode);
            this.checkDelete(tnode);
        }

        unit = this.unitMap[col+"_"+(row+1)];
        if( unit != null && unit.getValue() == value && this.deleteArr.indexOf(unit) == -1 && unit != this.selectedUnit)
        {
            tnode = DukeTree.produce();
            tnode.data = unit;
            this.deleteArr.push(unit);
            node.addChild(tnode);
            this.checkDelete(tnode);
        }

        unit = this.unitMap[col+"_"+(row-1)];
        if( unit != null && unit.getValue() == value && this.deleteArr.indexOf(unit) == -1  && unit != this.selectedUnit)
        {
            tnode = DukeTree.produce();
            tnode.data = unit;
            this.deleteArr.push(unit);
            node.addChild(tnode);
            this.checkDelete(tnode);
        }
    }
    private gap:number = 6;
    private cnt:number = 0;
    private fillMap:Object = {};
    private updateFillMap(hehe:string){
        var arr:any[] = hehe.split("_");
        if(arr.length == 2){
            var col:string = arr[0];
            var row:number = parseInt(arr[1]);
            var a:number[] = this.fillMap[col];
            if(a == null)
                this.fillMap[col] = [row];
            else
                a.push(row);
        }
    }
    private onEnterFrame(event:egret.Event){
        this.cnt++;
        if(this.cnt == this.gap ) {
            this.cnt = 0;
            var leaves:DukeNode[] = this.tree.getLeaves();
            var len:number = leaves.length;
            if( len > 0){
                var node:DukeNode;
                var unit:GameUnit;
                var pnode:DukeNode;
                var punit:GameUnit;
                var tw:egret.Tween;
                for(var i:number=0; i<len; i++){
                    node = leaves[i];
                    unit = node.data;
                    pnode = node.getParentNode();
                    punit = pnode.data;
                    tw = egret.Tween.get(unit,null, null, true);
                    tw.to({x:punit.x,y:punit.y},100).call(node.removeSelf,node);

                    pnode.removeChild(node);
                    this.updateScore(unit.getValue() * 10);

                    delete this.unitMap[unit.name];
                    this.updateFillMap(unit.name);
                }
            }else{
                this.removeEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
                if( this.selectedUnit != null){
                    var value = this.selectedUnit.getValue();
                    this.updateScore(value*10);
                    this.selectedUnit.setValue(value+1);
                    this.playHideParticle(this.selectedUnit);
                }
                this.tree.reset();
                egret.setTimeout(this.checkAndFill, this, 200);
            }
        }
    }

    private updateScore(value:number){
        this.score += value;
        this.scoreTf.text = "得分："+this.score;
    }

    //private psystem:particle.GravityParticleSystem;
    public playHideParticle(referUnit:GameUnit){
        return;
        //var temptextureName:string = "star";
        //this.psystem.stop(true);
        //if( this.currentTextureName != temptextureName)
        //{
        //    this.psystem.changeTexture(RES.getRes(temptextureName));
        //    this.currentTextureName = temptextureName;
        //}
        //
        //this.psystem.emitterX = referUnit.x;
        //this.psystem.emitterY = referUnit.y;
        //this.unitContainer.addChild(this.psystem);
        //this.psystem.start(100);
    }
    private checkAndFill(){//todo need to be optimized...
        var needCnt:number=-1;
        var unit:GameUnit;
        var idx:number;
        var tw:egret.Tween;
        var key;
        for(key in this.fillMap)
        {
            for(idx=this.row-1;idx>=0;idx--){
                unit = this.unitMap[key+"_"+idx];
                if( unit == null){
                    needCnt++;//fill empty ones
                }
                else{
                    if(needCnt >= 0)//move current ones
                    {
                        //unit.alpha = 0;
                        tw = egret.Tween.get(unit,null,null,true);
                        tw.to({y:unit.y+GameUnit.UNIT_WIDTH*(needCnt+1)},100);
                        delete this.unitMap[unit.name];
                        unit.name = key+"_"+(idx+needCnt+1);
                        this.unitMap[unit.name] = unit;
                    }
                }
            }
            while(needCnt >= 0)
            {
                unit = this.produceUnit();
                unit.setValue(this.getRandomValue());
                unit.name = key+"_"+needCnt;
                unit.x = parseInt(key)*GameUnit.UNIT_WIDTH;
                unit.y = - GameUnit.UNIT_WIDTH;
                unit.alpha = 1.0;
                this.unitContainer.addChildAt(unit,0);
                this.unitMap[unit.name] = unit;
                tw = egret.Tween.get(unit,null,null,true);
                tw.to({y:unit.y+GameUnit.UNIT_WIDTH*(needCnt+1)},100);
                needCnt--;
            }
            this.maxNumTf.text = "最大："+this.curMax;
        }
        egret.setTimeout(this.checkAllDeletable,this,600);
    }
    private checkAllDeletable(){
        var process:boolean = false;
        var key:string;
        var flag:boolean = false;
        Outer:
        for(var i:number=0; i< this.row; i++){
            for(var j:number=0; j< this.col; j++){
                key = j+"_"+i;
                this.tree.reset();
                this.deleteArr = [];
                this.selectedUnit = this.unitMap[key];
                var node:DukeNode = DukeTree.produce();
                node.data = this.unitMap[key];
                this.tree.setRoot(node);
                this.checkDelete(node);
                var len:number = this.deleteArr.length;
                //console.log("all again..: ",key," value : ",this.unitMap[key].getValue(), " len: ",len);
                if( len >= 2)
                {
                    this.score += len + 1;
                    this.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
                    process = true;
                    this.bonus++;

                    var hit:number = this.bonus <= 5 ? this.bonus : 5;
                    SoundMgr.getInstance().playEffect((hit+1)+"hit_wav");
                    flag = true;
                    break Outer;
                }
            }
        }

        if( !flag ){
            this.scoreTf.text = "得分："+this.score;
            this.blood += this.bonus;
            this.blood = Math.min(5, this.blood);
            this.bloodTf.text = "血量："+this.blood;
            //if( this.bonus >= 1 ){
            //    var effectId:number = this.bonus - 1;
            //    effectId = effectId > 3 ? 3 : effectId;
            //}
        }

        this.inProcessing = process;
    }
    private flag:boolean;
    public start(){
        if( this.flag){
            this.addEventListener(egret.Event.ENTER_FRAME,this.onEnterFrame,this);
            this.flag = false;
        }
    }

    public pause(){
        if( this.hasEventListener(egret.Event.ENTER_FRAME)){
            this.removeEventListener(egret.Event.ENTER_FRAME,this.onEnterFrame,this);
            this.flag = true;
        }
    }

    public produceUnit():GameUnit{
        if( this._unitCache.length > 0)
            return this._unitCache.pop();

        return new GameUnit();
    }

    public reclaimUnit(unit:GameUnit){
        if( this._unitCache.indexOf(unit) != -1)
            return;
        this._unitCache.push(unit);
        unit.reset();
    }

    public reset(){
        this.deleteArr = [];
        this.removeEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
        var unit:GameUnit;
        var key;
        for( key in this.unitMap){
            unit = this.unitMap[key];
            delete this.unitMap[key];
            this.reclaimUnit(unit);
            this.unitContainer.removeChild(unit);
        }
        var gap:number = GameUnit.UNIT_WIDTH;
        this.curMax = 0;
        this.curSeed = 5;
        this.blood = 5;
        this.getInitValues();
        for(var i:number = 0; i < this.col; i++){
            for(var j:number=0; j < this.row; j++){
                unit = this.produceUnit();
                unit.setValue(this.initValues[i*this.col+j]);
                unit.x = i * gap;
                unit.y = j * gap;
                this.unitContainer.addChild(unit);
                unit.name = i+"_"+j;
                this.unitMap[i+"_"+j] = unit;
            }
        }

        this.flag = false;
        this.isOver = false;
    }
    private static _instance:GameMain;
    public static instance():GameMain{
        if(GameMain._instance == null)
            GameMain._instance = new GameMain();
        return GameMain._instance;
    }
}
